<script setup>
import { ref, watch, reactive, provide } from 'vue'
import NameIcon from "./NameIcon.vue";
import draggable from "vuedraggable";
import FormPropsEditor from './controls/FormPropsEditor.vue';
import types from "./controls/controls";
import { randomWord, stringifyJson, parseJson } from "./utils";
import ItemRenderer from './controls/ItemDesignerGroup.vue'
const emit = defineEmits(['deleteItem', 'copyItem'])
//删除表单元素
const deleteItem = (data) => {
  emit('deleteItem', data)
}
//复制表单元素
const copyItem = (data) => {
  emit('copyItem', data)
}
const customForm = defineModel("customForm", {
  type: Object,
  required: true,
})
const controlGroups = defineModel("controlGroups", {
  type: Array,
  default: [{
    name: '基础组件',
    controls: ['input', 'textarea', 'inputnumber', 'select', 'radio', 'checkbox',
      'date', 'time', 'switch', 'text', 'divider'],
  },
  {
    name: '高级组件',
    controls: ['upload', 'uploadImage', 'region', 'cascader']
  },
  ]
})
//组件的属性
let props = defineProps({
  uploadOptions: {
    type: Object,
  },
  enData: {
    type: Array,
  },
  customComponents: {
    type: Array,
    default: function () { return [] }
  }
});
//加载用户自定义组件
const custom = props.customComponents
if (custom.length) {
  custom.forEach(item => {
    let group = controlGroups.value.find(g => g.name == item.groupName)
    if (!group) {
      group = {
        name: item.groupName,
        controls: []
      }
      controlGroups.value.push(group)

    }

    for (let key in item.components) {
      types[key] = item.components[key]
      group.controls.push(key)
    }
  })
}


//处理属性
controlGroups.value.forEach(group => {
  group.types = group.controls.map(key => types[key].Control);
});

provide('uploadOptions', props.uploadOptions);
// UI所需数据
let data = reactive({
  activeControl: null,
  propTab: "control",
  device: "pc"
});
provide('data', data);
provide('formProps', customForm.value.formContent.props);

let defaultFormProps = {
  labelPosition: "right",
  labelWidth: 100,
  size: "default",
  cols: 12,
};

if (customForm.value.formContent.controls == undefined) {
  customForm.value.formContent.controls = [];
}


if (customForm.value.formContent.props == undefined) {
  customForm.value.formContent.props = defaultFormProps;
} else {
  customForm.value.formContent.props = Object.assign(defaultFormProps, customForm.value.formContent.props);
}

//添加控件
function addControl(ctlType) {
  console.log(ctlType)
  var control = new ctlType();
  customForm.value.formContent.controls.push(control);
  data.activeControl = control;
}

//克隆控件
function clone(ctlType) {
  console.log('FormDesigner的clone方法')
  var control = new ctlType();
  return control;
}

//清空控件
function clearControl() {

  for (let i = customForm.value.formContent.controls.length - 1; i >= 0; i--) {
    let control = customForm.value.formContent.controls[i];
    if (!control.lock) {
      customForm.value.formContent.value.controls.splice(i, 1);
      if (control == data.activeControl) {
        data.activeControl = null;
      }
    }
  }

}
//#region 查看formJson
import { VAceEditor } from 'vue3-ace-editor';
import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-chrome';
// 语法检测 如果是只读，就不需要语法检测了
// import workerJsonUrl from 'ace-builds/src-noconflict/worker-json?url'; // For vite
// ace.config.setModuleUrl('ace/mode/json_worker', workerJsonUrl);
// :options="{ useWorker: true }"
let formJsonVisible = ref(false);
let formJson = ref(null);


function viewFormJson() {
  formJson.value = getFormJson()
  formJsonVisible.value = true;
}

function getFormJson() {
  console.log()
  return stringifyJson(customForm.value.formContent);
}

//#region 预览表单
import FormRenderer from './FormRenderer.vue';
import { ElMessage } from 'element-plus';
import FormViewer from './FormViewer.vue';


let previewVisible = ref(false);
let formRenderer = ref(null);
let previewData = reactive({
  formData: {},
  formModel: {}
})

function previewForm() {
  previewData.formData = parseJson(stringifyJson(customForm.value.formContent));
  let formModel = {};
  previewData.formData.controls.forEach(control => {
    if (control.props.defaultValue !== undefined)
      formModel[control.id] = control.props.defaultValue;
  });
  previewData.formModel = formModel;
  previewVisible.value = true;
}

function validate() {
  formRenderer.value.validate((valid) => {
    if (valid) {
      ElMessage.success('表单验证成功');
    } else {
      ElMessage.error('表单验证失败');
    }

  })
}

function resetFields() {
  formRenderer.value.resetFields();
}

//预览查看model数据
let modelJsonVisible = ref(false);
let modelDescVisible = ref(false);
let modelJson = ref(null);

function viewModelJson() {
  modelJson.value = JSON.stringify(previewData.formModel, null, 2);
  modelJsonVisible.value = true;
}

function viewModelDesc() {
  modelDescVisible.value = true;
}

//标题

// 暂未看到用途
defineExpose({
  getFormJson,
  clearControl,
});

// 表格数据

const getFormKey = () => {
  if (!customForm.value.formKey) {
    customForm.value.formKey = randomWord(false, 9)
  }
}
watch(customForm.value.formContent.controls, (newValue) => {
  customForm.value.formContent.controls = newValue
})
getFormKey()
</script>

<template>
  <el-dialog v-model="formJsonVisible" title="表单结构JSON" width="600px">
    <VAceEditor class="aceEditor" :readonly="true" v-model:value="formJson" lang="json" theme="chrome"
      style="height: 400px" />
    <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" @click="formJsonVisible = false">关闭</el-button>
      </span>
    </template>
  </el-dialog>

  <el-dialog v-model="previewVisible" destroy-on-close center fullscreen title="表单预览">
    <div class="epdf-preview-container">
      <FormRenderer ref="formRenderer" :formData="previewData.formData" :formModel="previewData.formModel" />

      <el-dialog v-model="modelJsonVisible" destroy-on-close title="表单数据JSON" width="600px">
        <VAceEditor class="aceEditor" :readonly="true" v-model:value="modelJson" lang="json" theme="chrome"
          style="height: 400px" />
        <template #footer>
          <span class="dialog-footer">
            <el-button type="primary" @click="modelJsonVisible = false">关闭</el-button>
          </span>
        </template>
      </el-dialog>

      <el-dialog v-model="modelDescVisible" destroy-on-close title="表单数据展示" width="600px">
        <div style="height: 400px; overflow-y: auto;">
          <FormViewer :formData="previewData.formData" :formModel="previewData.formModel" />
        </div>
        <template #footer>
          <span class="dialog-footer">
            <el-button type="primary" @click="modelDescVisible = false">关闭</el-button>
          </span>
        </template>
      </el-dialog>
    </div>
    <template #footer>
      <div class="epdf-preview-footer">
        <el-button type="primary" @click="viewModelJson">表单数据</el-button>
        <el-button type="primary" @click="viewModelDesc">表单查看</el-button>
        <el-button type="primary" @click="validate">验证表单</el-button>
        <el-button type="primary" @click="resetFields">重置表单</el-button>
        <el-button type="primary" @click="previewVisible = false">关闭</el-button>
      </div>
    </template>
  </el-dialog>

  <div class="epfd-container">
    <div class="epdf-left-board">
      <div v-for="(group, index) in controlGroups" :key="index">
        <div class="epdf-com-title">
          <el-icon>
            <NameIcon name="component" />
          </el-icon>
          <el-text>{{ group.name }}</el-text>
        </div>
        <draggable :list="group.types" item-key="type" tag="ul" class="epdf-com-group" :clone="clone" :sort="false"
          :group="{ name: 'com', pull: 'clone', put: false }">
          <template #item="{ element }">
            <li class="epdf-com-label" @click="addControl(element)">
              <el-icon>
                <NameIcon :name="element.type" :icon="element.icon" />
              </el-icon>
              <el-text size="small">{{ element.label }}</el-text>
            </li>
          </template>
        </draggable>
        <!-- <draggable></draggable> -->
      </div>
    </div>
    <div class="epdf-center-board">
      <div class="epdf-toolbar">

        <div class="epdf-opts">
          <!-- <el-form class="epdf-devices" label-width="100px" :inline="true">
            <el-form-item label="流程名称：" required>
              <el-input placeholder="" v-model="customForm.formName"></el-input>
            </el-form-item>
          </el-form> -->
          <el-popconfirm confirmButtonText="是" cancelButtonText="否" title="确定要清空组件吗?" @confirm="clearControl">
            <template #reference>
              <el-button text type="primary" :disabled="customForm.formContent.controls.length == 0">
                <el-icon>
                  <NameIcon name="clear" />
                </el-icon>
                <span>清空</span>
              </el-button>
            </template>
          </el-popconfirm>
          <el-button text type="primary" @click="viewFormJson">
            <el-icon>
              <NameIcon name="json" />
            </el-icon>
            <span>查看JSON</span>
          </el-button>
          <el-button text type="primary" @click="previewForm" :disabled="customForm.formContent.controls.length == 0">
            <el-icon>
              <NameIcon name="preview" />
            </el-icon>
            <span>预览</span>
          </el-button>
          <slot name="button"></slot>
        </div>
      </div>
      <div class="epdf-form-container" :class="[data.device]">
        <el-form ref="form" class="epdf-form" :label-position="customForm.formContent.props.labelPosition"
          :label-width="customForm.formContent.props.labelWidth" :size="customForm.formContent.props.size"
          :status-icon="false" :show-message="false">
          <ItemRenderer v-model:controls="customForm.formContent.controls" :uploadOptions="uploadOptions"
            @deleteItem="deleteItem" @copyItem="copyItem">
            <template #action="{ data }">
              <slot name="action" :data="data"></slot>
            </template>
          </ItemRenderer>
        </el-form>
      </div>
    </div>
    <div class="epdf-right-board">
      <el-tabs v-model="data.propTab">
        <el-tab-pane label="组件属性" name="control">
          <el-empty v-if="data.activeControl === null" description="请选择组件"></el-empty>
          <component v-else :is="types[data.activeControl.type].PropEditor" :control="data.activeControl"
            :formProps="customForm.formContent.props" :enData="props.enData" />
        </el-tab-pane>
        <el-tab-pane label="表单属性" name="form">
          <FormPropsEditor :formProps="customForm.formContent.props" />
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>

<style scoped lang="less">
.epfd-container {
  display: flex;
  justify-content: space-evenly;
  height: 100%;
  background-color: var(--el-color-info-light-9);


  .epdf-left-board {
    box-sizing: border-box;
    width: 200px;
    padding: 24px 16px 0 16px;
    // overflow-y: scroll;
    background-color: white;
    border-right: 1px solid var(--el-color-info-light-9);

    .epdf-com-title {
      .el-icon {
        vertical-align: baseline;
      }

      .el-text {
        margin-left: 4px;
      }
    }

    .epdf-com-group {
      display: flex;
      flex-direction: column;
      flex-wrap: wrap;
      padding-left: 0;
      gap: 6px;


      .epdf-com-label {
        width: 150px;
        height: 32px;
        display: flex;
        // flex-direction: column;
        justify-content: center;
        align-items: center;
        background-color: var(--el-color-info-light-8);
        border: 1px dashed white;

        .el-icon {
          margin-right: 12px;
        }

        &:hover {
          border: 1px dashed var(--el-color-primary);
          cursor: move;
        }
      }
    }
  }

  .epdf-center-board {
    box-sizing: border-box;
    flex-grow: 1;

    .epdf-devices {
      // width: 800px;
      text-align: end;
      line-height: 50px;

      .el-form-item {
        margin-bottom: 0;
        vertical-align: bottom;
      }
    }

    .epdf-toolbar {
      background-color: white;

      .epdf-opts {
        display: flex;
        justify-content: flex-end;
        height: 40px;
        align-items: end;

        .el-button {
          padding: 8px 16px;
          margin-left: 20px;
        }
      }
    }

    .epdf-form-container {
      margin: 12px;
      // height: calc(100%-10px);
      background-color: white;

      .epdf-form {
        margin-top: 8px;
        min-height: 700px;
        border: 1px dashed var(--el-color-info-dark-2);
      }
    }
  }



  .epdf-right-board {
    box-sizing: border-box;
    min-width: 350px;
    padding: 12px;
    overflow-y: scroll;
    background-color: white;
    border-left: 1px solid var(--el-color-info-light-8);
  }
}
</style>